import { Injectable } from '@nestjs/common';
import { AdminModelService } from 'src/model/admin-model/admin-model.service';
import { PermissionRoleModelService } from 'src/model/permission-role-model/permission-role-model.service';
import { PermissionRuleModelService } from 'src/model/permission-rule-model/permission-rule-model.service';
import { In } from 'typeorm';

const crypto = require('crypto')

@Injectable()
export class AdminService {
    constructor(
        private model:AdminModelService,
        private roleModel:PermissionRoleModelService,
        private ruleModel:PermissionRuleModelService,
    ) {}
    async validate(account:string, password:string) {
        const adminUser = await this.model.findOne({account : account}, ['adminId', 'password', 'salt'])
        if(!adminUser) return false

        password = crypto.createHash('md5').update(password + adminUser.salt).digest('hex')
        if(adminUser.password != password.toLowerCase()) return null

        return adminUser
    }

    async updateLogin(adminId, time:number) {
        this.model.update({adminId : adminId}, {lastLoginTime : time})
    }

    async checkeAuth(adminId:number, url:string) {
        const adminUser = await this.model.findOne({adminId}, ['super', 'roles'])
        if(!adminUser) return false

        if(adminUser.super) return true

        const roleIds = adminUser.roles as number[]

        if(!roleIds || roleIds.length == 0) return false

        const rows = await this.roleModel.find({id : In(roleIds)}, ['rules'])
        
        if(!rows || rows.length == 0) return false

        const ruleIds = []

        rows.forEach(row => {
            if(row.rules) {
                const rules = row.rules as number[]
                ruleIds.push(...rules)
            }
        } )

        const rules = await this.ruleModel.find({id : In(Array.from(new Set(ruleIds)))}, ['urls'])

        for(let i = 0; i < rules.length; i ++) {
            const urls = rules[i].urls as string[]
            if(urls && urls.includes(url)) return true
        }

        return false
    }
}
